﻿using BCCommon;
using BCData.Sim.Admin.Admin;
using BCData.Sim.Admin.AdminPermissionConfig;
using BCData.Sim.Admin.AdminPermissionRecord;
using BCData.Sim.Company.Department;
using BCDto.Sim.Admin.Admin;
using BCDto.Sim.Admin.AdminPermissionRecord;
using BCEntity.Common.EntityNameConst;
using BCEntity.Sim.Admin.AdminPermissionRecord;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;

namespace BCService.Sim.Admin.DepartmentPermissionRecord
{
    public class AdminPermissionRecordService : IDepartmentPermissionRecordService
    {
        private readonly IDatabaseContext databaseContext;
        private readonly IAdminPermissionConfigData adminPermissionConfigData; 
        private readonly IAdminPermissionRecordData adminPermissionRecordData;
        private readonly IDepartmentData departmentData;
        private readonly IAdminData adminData;
        private readonly IRedisService redisService;

        public AdminPermissionRecordService(IDatabaseContext databaseContext,
            IAdminPermissionConfigData adminPermissionConfigData,
            IAdminPermissionRecordData adminPermissionRecordData,
            IDepartmentData departmentData,
            IAdminData adminData,
            IRedisService redisService)
        {
            this.databaseContext = databaseContext;
            this.adminPermissionConfigData = adminPermissionConfigData;
            this.adminPermissionRecordData = adminPermissionRecordData;
            this.departmentData = departmentData;
            this.adminData = adminData;
            this.redisService = redisService;
        }

        public AdminPermissionRecordDto Setting(DepartmentPermissionRecordRequestDto requestDto)
        {
            if (requestDto.DepartmentId == 0 || !departmentData.CheckDepartment(requestDto.DepartmentId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("部门信息不存在");
            }
            if (string.IsNullOrWhiteSpace(requestDto.OperationPermission.Trim()))
            {
                throw new ArgumentException("操作权限不能为空");
            }
            if (requestDto.OperationPermission.IndexOf(".") == -1)
            {
                throw new ArgumentException("操作权限格式错误");
            }
            string[] operationPermission = requestDto.OperationPermission.Split(".");
            string permissionCode = operationPermission[0];
            string operstion = operationPermission[1];
            AdminPermissionRecordEntity entity = new AdminPermissionRecordEntity
            {
                PermissionCode = permissionCode,
                DepartmentId = requestDto.DepartmentId,
            };

            var recordEntity = this.adminPermissionRecordData.GetEntityByDepartmentIdAsync(requestDto.DepartmentId, permissionCode).GetAwaiter().GetResult();
            if (recordEntity != null)
            {
                entity.AdminPermissionRecordId = recordEntity.AdminPermissionRecordId;
                entity.EnabledInsert = recordEntity.EnabledInsert;
                entity.EnabledUpdate = recordEntity.EnabledUpdate;
                entity.EnabledDelete = recordEntity.EnabledDelete;
                entity.EnabledSelect = recordEntity.EnabledSelect;
                switch (operstion)
                {
                    case "Insert":
                        entity.EnabledInsert = !recordEntity.EnabledInsert;
                        break;
                    case "Update":
                        entity.EnabledUpdate = !recordEntity.EnabledUpdate;
                        break;
                    case "Delete":
                        entity.EnabledDelete = !recordEntity.EnabledDelete;
                        break;
                    default:
                        entity.EnabledSelect = !recordEntity.EnabledSelect;
                        break;
                }
                if (!entity.EnabledSelect)
                {
                    var permissionConfigEntity = this.adminPermissionConfigData.GetEntity(permissionCode).GetAwaiter().GetResult();
                    var permissionConfigList = this.adminPermissionConfigData.GetList().GetAwaiter().GetResult();
                    var permissionCodes = permissionConfigList.Where(p => p.PermissionPathCode.Contains(permissionConfigEntity.PermissionPathCode) && p.PermissionLevel > permissionConfigEntity.PermissionLevel).Select(p=>p.PermissionCode).ToList();
                    permissionCodes.Add(entity.PermissionCode);
                    this.adminPermissionRecordData.ClearPermissionAsync(permissionCodes, requestDto.DepartmentId);
                    return entity.As<AdminPermissionRecordDto>();
                }
                else
                {
                    var result = this.adminPermissionRecordData.UpdateDepartmentPermissionAsync(entity).GetAwaiter().GetResult().As<AdminPermissionRecordDto>();
                    if (result != null)
                    {
                        string key = string.Format("{0}:DepartmentId={1}", EntityNameConst.DepartmentPermissionListEntity, result.DepartmentId);
                        this.redisService.DeleteAsync(key);
                        string mappingKey = string.Format("{0}", EntityNameConst.AdminPermissionMappingPageViewDto);
                        string departmentKey = string.Format("{0}", EntityNameConst.DepartmentPermissionListEntity);
                        string adminRecordKey = string.Format("{0}", EntityNameConst.AdminPermissionRecordListEntity);
                        this.redisService.DeleteMultipleKey(mappingKey, false);
                        this.redisService.DeleteMultipleKey(departmentKey, false);
                        this.redisService.DeleteMultipleKey(adminRecordKey, false);
                    }
                    return result;
                }
            }
            else
            {
                entity.EnabledInsert = false;
                entity.EnabledUpdate = false;
                entity.EnabledDelete = false;
                entity.EnabledSelect = false;
                switch (operstion)
                {
                    case "Insert":
                        entity.EnabledInsert = true;
                        break;
                    case "Update":
                        entity.EnabledUpdate = true;
                        break;
                    case "Delete":
                        entity.EnabledDelete = true;
                        break;
                    default:
                        entity.EnabledSelect = true;
                        break;
                }
                var result = this.adminPermissionRecordData.InsertDepartmentPermissionRecordASync(entity).GetAwaiter().GetResult().As<AdminPermissionRecordDto>();
                if (result != null)
                {
                    string key = string.Format("{0}:DepartmentId={1}", EntityNameConst.DepartmentPermissionListEntity, entity.DepartmentId);
                    this.redisService.DeleteAsync(key);
                    string mappingKey = string.Format("{0}", EntityNameConst.AdminPermissionMappingPageViewDto);
                    string departmentKey = string.Format("{0}", EntityNameConst.DepartmentPermissionListEntity);
                    string adminRecordKey = string.Format("{0}", EntityNameConst.AdminPermissionRecordListEntity);
                    this.redisService.DeleteMultipleKey(mappingKey, false);
                    this.redisService.DeleteMultipleKey(departmentKey, false);
                    this.redisService.DeleteMultipleKey(adminRecordKey, false);
                }
                return result;
            }
        }

        public IEnumerable<AdminPermissionRecordDto> GetList(int departmentId)
        {
            string key = string.Format("{0}:DepartmentId={1}", EntityNameConst.DepartmentPermissionListEntity, departmentId);
            var result = this.redisService.TryGet(key, () => this.adminPermissionRecordData.GetDepartmentPermissionRecordListAsync(departmentId).GetAwaiter().GetResult(), new TimeSpan(1, 0, 0, 0, 0));
            if (result.Any())
            {
                bool rootSelectEnabled = false;
                foreach(var item in result)
                {
                    if (item.PermissionLevel == 0)
                    {
                        rootSelectEnabled = item.EnabledSelect;
                    }
                    else
                    {
                        item.Disabled = !rootSelectEnabled;
                    }
                }
            }
            return result.As<IEnumerable<AdminPermissionRecordDto>>();
        }

        public void DeleteDepartmentPermission(AdminDto admin, int departmentId, string operationPermissionRequest)
        {
            if (!this.departmentData.CheckDepartment(departmentId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("部门信息不存在。");
            }
            if (string.IsNullOrWhiteSpace(operationPermissionRequest.Trim()))
            {
                throw new ArgumentException("操作权限不能为空");
            }
            if (operationPermissionRequest.IndexOf(".") == -1)
            {
                throw new ArgumentException("操作权限格式错误");
            }
            string[] operationPermission = operationPermissionRequest.Split(".");
            string permissionCode = operationPermission[0];
            string operstion = operationPermission[1];
            var recordEntity = this.adminPermissionRecordData.GetEntityByDepartmentIdAsync(departmentId, permissionCode).GetAwaiter().GetResult();
            //AdminPermissionRecordEntity entity = new AdminPermissionRecordEntity
            //{
            //    PermissionCode = permissionCode,
            //    DepartmentId = departmentId,
            //    AdminPermissionRecordId = recordEntity.AdminPermissionRecordId
            //};
            if (recordEntity != null)
            {
                switch (operstion)
                {
                    case "Insert":
                        recordEntity.EnabledInsert = false;
                        break;
                    case "Update":
                        recordEntity.EnabledUpdate = false;
                        break;
                    case "Delete":
                        recordEntity.EnabledDelete = false;
                        break;
                    default:
                        recordEntity.EnabledSelect = false;
                        break;
                }
                databaseContext.BeginTransaction();
                if (!recordEntity.EnabledSelect)
                {
                    var permissionConfigEntity = this.adminPermissionConfigData.GetEntity(permissionCode).GetAwaiter().GetResult();
                    var permissionConfigList = this.adminPermissionConfigData.GetList().GetAwaiter().GetResult();
                    var permissionCodes = permissionConfigList.Where(p => p.PermissionPathCode.Contains(permissionConfigEntity.PermissionPathCode) && p.PermissionLevel > permissionConfigEntity.PermissionLevel).Select(p => p.PermissionCode).ToList();
                    permissionCodes.Add(recordEntity.PermissionCode);
                    this.adminPermissionRecordData.ClearPermissionAsync(permissionCodes, departmentId);
                }
                this.adminPermissionRecordData.DeleteDepartmentPermissionAsync(recordEntity).GetAwaiter().GetResult();
                string key = string.Format("{0}:DepartmentId={1}", EntityNameConst.DepartmentPermissionListEntity, departmentId);
                this.redisService.DeleteAsync(key);
                string mappingKey = string.Format("{0}", EntityNameConst.AdminPermissionMappingPageViewDto);
                string departmentKey = string.Format("{0}", EntityNameConst.DepartmentPermissionListEntity);
                string adminRecordKey = string.Format("{0}", EntityNameConst.AdminPermissionRecordListEntity);
                this.redisService.DeleteMultipleKey(mappingKey, false);
                this.redisService.DeleteMultipleKey(departmentKey, false);
                this.redisService.DeleteMultipleKey(adminRecordKey, false);
                var departmentEntity = departmentData.GetById(departmentId).GetAwaiter().GetResult();
                List<string> departmentIds = new List<string>();
                bool startInput = false;
                string departmentIdStr = departmentId.ToString();
                int i = 0;
                foreach (var item in departmentEntity.DepartmentPath.Split())
                {
                    if (i > 0)
                    {
                        if (item.Equals(departmentIdStr))
                        {
                            startInput = true;
                        }
                        if (startInput)
                        {
                            departmentIds.Add(item);
                        }
                    }
                    i++;
                }
                string departmentIdPath = string.Join(',', departmentIds);
                var adminIds = this.adminData.GetByDepartmentIdAsync(departmentIdPath).GetAwaiter().GetResult();
                if (adminIds.Any())
                {
                    foreach (var adminId in adminIds)
                    {
                        string adminKey = string.Format("{0}:AdminId={1}", EntityNameConst.AdminDto, adminId);
                        this.redisService.DeleteAsync(adminKey);
                    }
                }
                databaseContext.Commit();
            }
        }
    }
}
